import React, { ChangeEvent, DragEvent, FC, useRef, useState } from "react"
import axios from "axios"
import Button, { ButtonType } from "../Button"
import UploadList from "../UploadList"

export type UploadFileStatus = "ready" | "uploading" | "success" | "error"

export interface UploadFile {
	uid: string
	size: number
	name: string
	status?: UploadFileStatus
	percent?: number
	raw?: File
	response?: any
	error?: any
}

export interface UploadProps {
	action: string
	defaultFileList?: UploadFile[]
	beforeUpload?: (file: File) => boolean | Promise<File>
	onProgress?: (percent: number, file: File) => void
	onSuccess?: (data: any, file: File) => void
	onError?: (err: any, file: File) => void
	onComplete?: (file: File) => void
	onRemove?: (file: UploadFile) => void
	headers?: { [key: string]: any }
	name?: string
	data?: { [key: string]: any }
	withCredentials?: boolean
	accept?: string
	multiple?: boolean
	drag?: boolean
}

const Upload: FC<UploadProps> = props => {
	const { action, beforeUpload, onProgress, onSuccess, onError, onComplete, defaultFileList, onRemove, headers, name, data, withCredentials, accept, multiple, drag } = props

	const inputRef = useRef<HTMLInputElement>(null)
	const [fileList, setFileList] = useState<UploadFile[]>(defaultFileList || [])
	const updateFileList = (updateFile: UploadFile, updateObj: Partial<UploadFile>) => {
		setFileList(prevList => {
			return prevList.map(file => {
				if (file.uid === updateFile.uid) {
					return {
						...file,
						...updateObj,
					}
				} else {
					return file
				}
			})
		})
	}
	const handleButtonClick = () => {
		console.log("handleButtonClick")
		inputRef.current?.click()
	}
	const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
		const files = e.target.files
		if (!files) return
		uploadFiles(files)
		if (inputRef.current) {
			inputRef.current.value = ""
		}
	}
	const uploadFiles = (files: FileList) => {
		const arrFiles = Array.from(files)
		arrFiles.forEach(file => {
			if (!beforeUpload) {
				uploadSingleFile(file)
			} else {
				const res = beforeUpload(file)
				if (res instanceof Promise) {
					res.then(processedFile => {
						uploadSingleFile(processedFile)
					})
				} else {
					if (res) {
						uploadSingleFile(file)
					}
				}
			}
		})
	}
	const uploadSingleFile = (file: File) => {
		let _file: UploadFile = {
			uid: Date.now() + "upload-file",
			status: "ready",
			size: file.size,
			name: file.name,
			percent: 0,
			raw: file,
		}
		// setFileList([_file, ...fileList])
		setFileList(prevList => {
			return [_file, ...prevList]
		})
		const formData = new FormData()
		formData.append(name || "file", file)
		if (data) {
			Object.keys(data).forEach(key => {
				formData.append(key, data[key])
			})
		}
		axios
			.post(action, formData, {
				headers: {
					"Content-Type": "multipart/form-data",
					...headers,
				},
				withCredentials,
				onUploadProgress(e) {
					let percentage = Math.round((e.loaded * 100) / e.total) || 0
					if (percentage < 100) {
						updateFileList(_file, { percent: percentage, status: "uploading" })
						onProgress && onProgress(percentage, file)
					}
				},
			})
			.then(res => {
				onSuccess && onSuccess(res.data, file)
				updateFileList(_file, { status: "success", response: res.data })
				onComplete && onComplete(file)
			})
			.catch(err => {
				onError && onError(err, file)
				updateFileList(_file, { status: "error", error: err })
				onComplete && onComplete(file)
			})
	}
	const handleRemove = (file: UploadFile) => {
		setFileList(prevList => {
			return prevList.filter(item => item.uid !== file.uid)
		})
		onRemove && onRemove(file)
	}

	const handleButtonDragOver = (e: DragEvent<HTMLElement>) => {
		e.preventDefault()
		console.log("handleButtonDragOver ===> 1")
	}

	const handleButtonDrop = (e: DragEvent<HTMLElement>) => {
		e.preventDefault()
		console.log("dataTransfer ===> 2", e.dataTransfer.files)
	}

	const handleButtonDragLeave = () => {
		console.log("handleButtonDragLeave ===> 3")
	}

	return (
		<div>
			<Button btnType={ButtonType.Primary} onClick={handleButtonClick} onDragOver={handleButtonDragOver} onDrop={handleButtonDrop} onDragLeave={handleButtonDragLeave}>
				Upload File
			</Button>

			<input ref={inputRef} className="viking-file-input" style={{ display: "none" }} type="file" onChange={handleFileChange} accept={accept} multiple={multiple} />
			<UploadList fileList={fileList} onRemove={handleRemove}></UploadList>
		</div>
	)
}

Upload.defaultProps = {
	name: "file",
}

export default Upload
